﻿/*
* 作 者: 槐尧
* 创建时间: 2016/2/17 16:11:56
* 说明:  
*/

using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;

namespace MYTC
{
    public interface ISubject
    {

    }

    public interface INotificationHandler<Type>
    where Type : class,ISubject
    {
        void OnNotify(Type message);
    }


    class NotificationFunctor<Type> : INotificationHandler<Type>
    where Type : class, ISubject
    {
        Action<Type> functor;
        public NotificationFunctor(Action<Type> func)
        {
            functor = func;
        }

        public void OnNotify(Type message)
        {
            if (functor != null)
                functor(message);
        }
    }

    public class Subject<Type> : ISubject
    where Type : Subject<Type>, new()
    {
        Type self;
        List<INotificationHandler<Type>> handlers;

        public Type Clone()
        {
            Type ret = new Type();
            ret.handlers = new List<INotificationHandler<Type>>(this.handlers);
            return ret;
        }

        protected Subject()
        {
            self = (Type)this;
            handlers = new List<INotificationHandler<Type>>();
        }

        public bool Subscribe(INotificationHandler<Type> handler)
        {
            if (handlers.Contains(handler))
                return true;

            handlers.Add(handler);
            return true;
        }

        public bool Unsubscribe(INotificationHandler<Type> handler)
        {
            if (!handlers.Contains(handler))
                return true;

            return handlers.Remove(handler);
        }

        public void Broadcast( object message) 
        {
            foreach (var handler in handlers)
                handler.OnNotify(message as Type);
        }

        public void Broadcast()
        {
            foreach (var handler in handlers)
                handler.OnNotify(self);
        }

        public void Notify(INotificationHandler<Type> handler)
        {
            if (handler != null)
                handler.OnNotify(self);
        }
    }

    public class NotificationCenter
    {
        private static NotificationCenter m_instance;

        public static NotificationCenter Instance
        {
            get 
            {
                if (m_instance == null)
                {
                    m_instance = new NotificationCenter();
                }
                return NotificationCenter.m_instance; 
            }
        }

        Dictionary<Type, ISubject> msgTemplates;
        private NotificationCenter()
        {
            msgTemplates = new Dictionary<Type, ISubject>();
        }

        public INotificationHandler<Type> Subscribe<Type>(Action<Type> func)
        where Type : Subject<Type>, new()
        {
            var handler = new NotificationFunctor<Type>(func);
            Subscribe<Type>(handler);
            return handler;
        }


        public bool Subscribe<Type>(INotificationHandler<Type> handler)
            where Type : Subject<Type>, new()
        {
            Type msg = null;
            var key = typeof(Type);
            if (msgTemplates.ContainsKey(key))
            {
                msg = (Type)msgTemplates[key];
            }
            else
            {
                msg = new Type();
                msgTemplates[key] = msg;
            }

            return (msg == null) ? false : ((Type)msg).Subscribe(handler);
        }

        public bool Unsubscribe<Type>(INotificationHandler<Type> handler)
            where Type : Subject<Type>, new()
        {
            var key = typeof(Type);
            if (!msgTemplates.ContainsKey(key))
            {
                return true;
            }

            Type msg = (Type)msgTemplates[key];
            return msg.Unsubscribe(handler);
        }

        public Type Notification<Type>()
            where Type : Subject<Type>, new()
        {
            var key = typeof(Type);
            if (!msgTemplates.ContainsKey(key))
            {
                // return dummy notification
                return new Type();
            }

            var msg = (Type)msgTemplates[key];
            var ret = msg.Clone();
            return ret;
        }

        public void Broadcast<Type>(Type message) where Type : Subject<Type>, new()
        {
            var key = typeof(Type);
            if (!msgTemplates.ContainsKey(key))
            {
                // return dummy notification
                UnityEngine.Debug.Log("do not exist");
                return;
            }

            var msg = (Type)msgTemplates[key];
            msg.Broadcast(message);
        }

    }

    class MTNotification 
    {

    }
}

